package main

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

type Rw interface {
	Rd(key string, duration time.Duration) interface{}
	Wt(key string, value interface{})
}

type myRw struct {
	sync.RWMutex
	info map[string]*Info
}
type Info struct {
	ch    chan bool
	value interface{}
}

func (m *myRw) Wt(key string, value interface{}) {
	m.Lock()
	defer m.Unlock()
	if v, ok := m.info[key]; ok {
		v.value = value
		v.ch <- true
	} else {
		vv := &Info{
			ch:    make(chan bool, 1),
			value: value,
		}
		vv.ch <- true
		m.info[key] = vv
	}
}

func (m *myRw) Rd(key string, duration time.Duration) interface{} {
	ch := make(chan bool)

	go func(ch chan<- bool) {
		for {
			m.Lock()
			_, ok := m.info[key]

			m.Unlock()
			if ok {

				ch <- true
			
				return
			}
		}
	}(ch)
	select {
	case <-ch:
		m.Lock()
		defer m.Unlock()
		fmt.Println(m.info[key])
		return m.info[key]
	case <-time.After(duration * time.Second):
		fmt.Printf("timeout.... key = %s\n", key)
		return nil
	}
	return nil
}

func main() {
	info := &myRw{
		info: make(map[string]*Info),
	}
	go func() {
		for i := 0; i < 10; i++ {
			info.Wt(strconv.Itoa(i), i)
			time.Sleep(time.Second)
		}
	}()
	go func() {
		for i := 0; i < 10; i++ {
			info.Rd(strconv.Itoa(i), 1)
		}
	}()
	time.Sleep(10 * time.Second)
	fmt.Println("main........")
}
